/**************************************************************************
                          clonenamesearch.c

written by IL
edited by CAS
***************************************************************************/
#include "fpp.h"
#include <ctype.h>

extern int PRTMESS;
int Zfp_match(int c1, int c2);

/* WMN name changed for mac build */
BOOL strcasestr_priv(char *line,char *search)
/* NOTE search must be in lower case before this point (use lowerstring)*/
/* only line is copied and made lowercase */
{
  char templine[80];
  int i;

  for(i=0;i<strlen(line);i++){
    templine[i] = tolower(line[i]);
  }
  templine[i] = line[i];

  if (strstr(templine,search)){
    return TRUE;
  }
  else
    return FALSE;
}

void lowerstring(char *search)
{
  int i;

  for(i=0;i<strlen(search);i++)
    search[i] = tolower(search[i]);
  
  return;
}

void clonenamesearch()
{
  struct list *p=NULL;
  int i,j,max; 
  BOOL found;

  if (acedata==NULL) return;
  max = arrayMax(acedata);

  found = FALSE;
  j=0;
  while(!found){
	if(arrp(acedata,j,CLONE)->clone[0] != '!'){
	  listroot  = (struct list *)messalloc((sizeof(struct list)));	
	  listroot->index = j;
	  listroot->next = NULL;
	  p = listroot;
	  found = TRUE;
	}
	j++;
  }
  for(i=j;i<max;i++){
     if(p!=NULL){
	p->next  = (struct list *)messalloc((sizeof(struct list)));	
	p=p->next;
	p->index= i;
     }
  }
  if(p!=NULL) p->next = NULL;
}

void subclonesearch()
{
  struct list *p=NULL,*oldroot,*temp,*q;
  int i,j,index,len, lencl,pos; 
  char search[CLONE_SZ+1],search2[CLONE_SZ+1];
  CLONE *clone;
  BOOL found,first;
  char str1[80];

  strcpy(search,chsearchglob);
  if (search[0]=='\0' || search[0]=='\n') strcpy(search,"*");

  if (acedata==NULL) return;
  q = listroot;
  oldroot = listroot;
  listroot = NULL;

  if(strcmp(search,"*")==0){ /* if all to be found */
    found = TRUE;
    listroot = oldroot;
    displaykeyset(1);
    return;
  }
  else if(search[0] == '*'){          /* starts with * */
    j =0;
    for(i=1;i<CLONE_SZ;i++){ /* get the char bit */
      search[j++]=search[i];
    }
    if(strstr(search,"*")!=NULL){    /* if there is another * then format is *char* */
      first = TRUE;
      j =0;
      for(i=0;i<CLONE_SZ;i++){ /* get the char bit */
	if(search[i]!='*')
	  search2[j++]=search[i];
	else{
	  search2[j++]='\0';
	  break;
	}
      }
      lowerstring(search2);
      while(q!=NULL){
	clone = arrp(acedata,q->index,CLONE);
	if(strcasestr_priv(clone->clone,search2) && clone->clone[0] != '!'){
	  if(first){
	    listroot  = (struct list *)messalloc((sizeof(struct list)));	
	    listroot->next = NULL;
	    p = listroot;
	    p->index = q->index;
	    first = FALSE;
	  }
	  else{
	    p->next = (struct list *)messalloc((sizeof(struct list)));	
	    p=p->next;
	    p->index = q->index;
	  }
	}	  
	q=q->next;
      }
      if(!first)
	p->next = NULL;
    }
    else{                     /* format is *char */ 
      len = strlen(search);	
      first = TRUE;
      while(q!=NULL){
	clone = arrp(acedata,q->index,CLONE);
	lencl = strlen(clone->clone);
	found = TRUE;
	for(j=len;j>=0;j--){
	  /*if(search[j]!=clone->clone[lencl--])*/
	  if(tolower(search[j])!=tolower(clone->clone[lencl--])){   /*efriedr 1/25/02 -- make case insensitive -- UPDATE 3/8/02*/
	    found = FALSE;
	    break;
	  }
	}
	if(clone->clone[0] == '!')
	  found = FALSE;
	if(found){
	  if(first){
	    listroot  = (struct list *)messalloc((sizeof(struct list)));	
	    listroot->next = NULL;
	    p = listroot;
	    p->index = q->index;
	    first = FALSE;
	  }
	  else{
	    p->next = (struct list *)messalloc((sizeof(struct list)));	
	    p=p->next;
	    p->index = q->index;
	  }
	}	  
	q=q->next;
      } /* end while */
      if(!first)
	p->next = NULL;
    }
  }
  else if (strstr(search,"*")!=NULL){   /* the format is char* */
    pos = 0;
    for(i=0;i< CLONE_SZ;i++){
      if(search[i]=='*'){
	pos= i;
	break;
      }
    }
    if(pos == 0)
      printf("error * not found but should be ????\n");
    first = TRUE;
    while(q!=NULL){
      clone = arrp(acedata,q->index,CLONE);
      if(strncasecmp(search,clone->clone,pos)==0){
	if(first){
	  listroot  = (struct list *)messalloc((sizeof(struct list)));	
	  listroot->next = NULL;
	  p = listroot;
	  p->index = q->index;
	  first = FALSE;
	}
	else{
	  p->next = (struct list *)messalloc((sizeof(struct list)));	
	  p=p->next;
	  p->index = q->index;
	}
      }	 
      q=q->next;
    }
    if(!first)
      p->next = NULL;
  }
  else{                  /* no special characters */
    if(fppFind(acedata,search,&index, cloneOrder)){
      listroot  = (struct list *)messalloc((sizeof(struct list)));	
      listroot->next = NULL;
      p = listroot;
      p->index = index;    
    }
    else{   /*fred 11/13/02 -- if not exact, check for substring*/
       printf("Exact match (Name=%s) not found.  Looking for substring.\n",search);
       first = TRUE;
       while(q!=NULL){
         clone = arrp(acedata,q->index,CLONE);
         lowerstring(search);
         if(strcasestr_priv(clone->clone,search)){
	   if(first){
	     listroot  = (struct list *)messalloc((sizeof(struct list)));	
	     listroot->next = NULL;
	     p = listroot;
	     p->index = q->index;
	     first = FALSE;
	   }
	   else{
	     p->next = (struct list *)messalloc((sizeof(struct list)));	
	     p=p->next;
	     p->index = q->index;
	   }
         }	 
         q=q->next;
       }
       if(!first)
         p->next = NULL;
    }

  }
  if(listroot==NULL){
    listroot = oldroot;
    i=0;
    while(oldroot != NULL){
      i++;
      oldroot= oldroot->next;
    }
    sprintf(str1,"Clone search (Name=%s) failed for keyset of %d items.",chsearchglob, i);
    if (PRTMESS) displaymess(str1);
    displaykeyset(0);
  }
  else{
    page = 0;
    p= oldroot;
    while(p!=NULL){
      temp=p;
      p=p->next;
      if(!messfree(temp))
        printf("error freeing list memory\n");
    }
    displaykeyset(1);
  }
  graphPop();
}

void destarandlower(char *temp)
{
  char temp2[CLONE_SZ+1];
  int i,j,l;

  strcpy(temp2,temp);
  l = strlen(temp);
  for(i=0,j=0;i<=l;i++){
    if(temp2[i]!='*')
      temp[j++]=tolower(temp[i]);
  }
}

void remsearch()
{
  char search[CLONE_SZ+1];
  BOOL added,first=TRUE;
  struct list *p=NULL,*oldroot,*temp,*q;
  CLONE *clone;
  struct remark *rem;
  int i;
  char str1[120];

  strcpy(search,chsearchglob);

  destarandlower(search);
  if (acedata==NULL) return;
  q= listroot;
  oldroot = listroot;
  listroot = NULL;

  while(q!=NULL){
    added =FALSE;
    clone = arrp(acedata,q->index,CLONE);
    rem = clone->remark;
    while(rem != NULL && !added){
      if(!strcasecmp(rem->message,search)){
	added = TRUE;
	if(first){
	  listroot  = (struct list *)messalloc((sizeof(struct list)));	
	  listroot->next = NULL;
	  p = listroot;
	  p->index = q->index;
	  first = FALSE;
	}
	else{
	  p->next = (struct list *)messalloc((sizeof(struct list)));	
	  p=p->next;
	  p->index = q->index;
	}
      }
      rem = rem->next;
    }
    rem = clone->fp_remark;
    while(rem != NULL && !added){
      if(!strcasecmp(rem->message,search)){
	added = TRUE;
	if(first){
	  listroot  = (struct list *)messalloc((sizeof(struct list)));	
	  listroot->next = NULL;
	  p = listroot;
	  p->index = q->index;
	  first = FALSE;
	}
	else{
	  p->next = (struct list *)messalloc((sizeof(struct list)));	
	  p=p->next;
	  p->index = q->index;
	}
      }
      rem = rem->next;
    }
    q=q->next;
  }
  if(listroot==NULL){
     printf("Exact match (Remark=%s) not found.  Looking for substring.\n",search);
     q=oldroot;
     while(q!=NULL){
       added =FALSE;
       clone = arrp(acedata,q->index,CLONE);
       rem = clone->remark;
       while(rem != NULL && !added){
         if(strcasestr_priv(rem->message,search)){
	   added = TRUE;
	   if(first){
	     listroot  = (struct list *)messalloc((sizeof(struct list)));	
	     listroot->next = NULL;
	     p = listroot;
	     p->index = q->index;
	     first = FALSE;
	   }
	   else{
	     p->next = (struct list *)messalloc((sizeof(struct list)));	
	     p=p->next;
	     p->index = q->index;
	   }
         }
         rem = rem->next;
       }
       rem = clone->fp_remark;
       while(rem != NULL && !added){
         if(strcasestr_priv(rem->message,search)){
	   added = TRUE;
	   if(first){
	     listroot  = (struct list *)messalloc((sizeof(struct list)));	
	     listroot->next = NULL;
	     p = listroot;
	     p->index = q->index;
	     first = FALSE;
	   }
	   else{
	     p->next = (struct list *)messalloc((sizeof(struct list)));	
	     p=p->next;
	     p->index = q->index;
	   }
         }
         rem = rem->next;
       }
       q=q->next;
     }
  }
  if(listroot==NULL){
    listroot = oldroot;
    i=0;
    while(oldroot != NULL){
      i++;
      oldroot= oldroot->next;
    }
    sprintf(str1,"Clone search (Remark=%s) failed for keyset of %d items.",chsearchglob, i);
    if (PRTMESS) displaymess(str1);
    displaykeyset(0);
  }
  else{
    page = 0;
    p= oldroot;
    while(p!=NULL){
      temp=p;
      p=p->next;
      if(!messfree(temp))
        printf("error freeing list memory\n");
    }
    displaykeyset(1);
  }
  graphPop();
}

void notremsearch()
{
  char search[CLONE_SZ+1];
  BOOL addit,first=TRUE;
  struct list *p=NULL,*oldroot,*temp,*q;
  CLONE *clone;
  struct remark *rem;
  int i;
  char str1[120];

  strcpy(search,chsearchglob);

  destarandlower(search);
  if (acedata==NULL) return;
  q= listroot;
  oldroot = listroot;
  listroot = NULL;

  while(q!=NULL){
    addit =TRUE;
    clone = arrp(acedata,q->index,CLONE);
    rem = clone->remark;
    while(rem != NULL && addit){
      if(strcasestr_priv(rem->message,search)){
	addit = FALSE;
      }
      rem = rem->next;
    }
    rem = clone->fp_remark;
    while(rem != NULL && addit){
      if(strcasestr_priv(rem->message,search)){
	addit = FALSE;
      }
      rem = rem->next;
    }
    if(addit){
      if(first){
	listroot  = (struct list *)messalloc((sizeof(struct list)));	
	listroot->next = NULL;
	p = listroot;
	p->index = q->index;
	first = FALSE;
      }
      else{
	p->next = (struct list *)messalloc((sizeof(struct list)));	
	p=p->next;
	p->index = q->index;
      }
    }
    q=q->next;
  }
  if(listroot==NULL){
    listroot = oldroot;
    i=0;
    while(oldroot != NULL){
      i++;
      oldroot= oldroot->next;
    }
    sprintf(str1,"Clone search (!Remark=%s) failed for keyset of %d items.",chsearchglob, i);
    if (PRTMESS) displaymess(str1);
    listroot = oldroot;
    displaykeyset(0);
  }
  else{
    page = 0;
    p= oldroot;
    while(p!=NULL){
      temp=p;
      p=p->next;
      if(!messfree(temp))
        printf("error freeing list memory\n");
    }
    displaykeyset(1);
  }
  graphPop();
}

void gelsearch()
{
  BOOL added,first=TRUE;
  struct list *p=NULL,*oldroot,*temp,*q;
  CLONE *clone;
  struct fpdata *fp;
  char str1[180];
  char gelname[GEL_SZ+1];
  int i;
  char destar[50];

  strcpy(gelname,chsearchglob);
    /* allow star at end - allows substring anywhere, 3dec99 */
  if (gelname[strlen(gelname)-1]=='*') {
      strcpy(destar, gelname);
      destar[strlen(destar)-1]='\0';
  } 
  else strcpy(destar,"ZXCVBNMML>");
   
  if (acedata==NULL) return;
  q= listroot;
  oldroot = listroot;
  listroot = NULL;

  while(q!=NULL){
    added =FALSE;
    clone = arrp(acedata,q->index,CLONE);
    fp = clone->fp;
    while(fp != NULL && !added){
      if(strcasecmp(fp->gelname, gelname)==0 || strstr(fp->gelname,destar)!=0){
	added = TRUE;
	if(first){
	  listroot  = (struct list *)messalloc((sizeof(struct list)));	
	  listroot->next = NULL;
	  p = listroot;
	  p->index = q->index;
	  first = FALSE;
	}
	else{
	  p->next = (struct list *)messalloc((sizeof(struct list)));	
	  p=p->next;
	  p->index = q->index;
	}
      }
      fp = fp->next;
    }
    q=q->next;
  }
  if(listroot==NULL){
    listroot = oldroot;
    i=0;
    while(oldroot != NULL){
      i++;
      oldroot= oldroot->next;
    }
    sprintf(str1,"Clone search (Gel=%s) failed for keyset of %d items.",gelname, i);
    if (PRTMESS) displaymess(str1);
    displaykeyset(0);
  }
  else{
    page = 0;
    p= oldroot;
    while(p!=NULL){
      temp=p;
      p=p->next;
      if(!messfree(temp))
        printf("error freeing list memory\n");
    }
    displaykeyset(1);
  }
  graphPop();
}

/**********************************************
               DEF: FPsearch
**********************************************/
void FPsearch()
{
  char search[CLONE_SZ+1];
  BOOL first=TRUE;
  struct list *p=NULL,*oldroot,*temp,*q;
  int index;
  int i;

  strcpy(search,chsearchglob);
  if(!fppFind(acedata,search,&index,cloneOrder)){
    printf("%s is not a valid clone. Try again\n",search);
    return;
  }
   
  if(!bands) fpRead();
    
  if (acedata==NULL) return;
  q= listroot;
  oldroot = listroot;
  listroot = NULL;

  while(q!=NULL){
    if(Zfp_match(index,q->index)){
      if(first){
	listroot  = (struct list *)messalloc((sizeof(struct list)));	
	listroot->next = NULL;
	p = listroot;
	p->index = q->index;
	first = FALSE;
      }
      else{
	p->next = (struct list *)messalloc((sizeof(struct list)));	
	p=p->next;
	p->index = q->index;
      }
    }
    q=q->next;
  }
  if(listroot==NULL){
    listroot = oldroot;
    i=0;
    while(oldroot != NULL){
      i++;
      oldroot= oldroot->next;
    }
    printf("Clone search (Fingerprint=%s) failed for keyset of %d items.\n",
          search, i);
    displaykeyset(0);
  }
  else{
    page = 0;
    p= oldroot;
    while(p!=NULL){
      temp=p;
      p=p->next;
      if(!messfree(temp))
        printf("error freeing list memory\n");
    }
    displaykeyset(1);
  }
  graphPop();
}

/**************************************************************
                   DEF: comparedates
used by Marker and Clone date searches
Note: you must make changes to the year to deal with >2000
**************************************************************/
int comparedates(struct mytime *cmpdate,struct mytime *date)
/* return +1 if date is newer than cmpdate and -1 if older */
{
  /*
  jhat - not necessary since all dates are stored as year - 1900
	i.e., 1999 is 99, and 2001 is 101, so they will compare correctly

  if (cmpdate->year >= 70) cmpyear = cmpdate->year + 1900;
  else cmpyear = cmpdate->year + 2000;

  if (date->year >= 70) year = date->year + 1900;
  else year = date->year + 2000;
  */

  if(date->year < cmpdate->year)
    return -1;
  else if(date->year > cmpdate->year)
    return 1;

  if(date->month < cmpdate->month)
    return -1;
  else if(date->month > cmpdate->month)
    return 1;
  if(date->day < cmpdate->day)
    return -1;
  else if(date->day > cmpdate->day)
    return 1;
  if(date->hour < cmpdate->hour)
    return -1;
  else if(date->hour > cmpdate->hour)
    return 1;
  if(date->minute < cmpdate->minute)
    return -1;
  else if(date->minute > cmpdate->minute)
    return 1;

  return 0;
}

void creationdates_clone(int result,BOOL created)
/* if result = -1 then check before if result = 1 check after */
{
  struct mytime searchdate,cmpdate,curdate;
  struct tm *curr_time;
  time_t ltime;
  char search[CLONE_SZ+1];
  BOOL first=TRUE;
  struct list *p=NULL,*oldroot,*temp,*q;
  CLONE *clone;
  char str1[180];
  int junk1,junk2,junk3,i;

  strcpy(search,chsearchglob);
  if(sscanf(search,"%d/%d/%d",&searchdate.day,&searchdate.month,&searchdate.year)!=3){
    sprintf(str1,"The date \"%s\" is not in the correct format (dd/mm/yy hh:mm). hh:mm are optional. Try again",search);
    if (PRTMESS) displaymess(str1);
    return;
  }
  if(sscanf(search,"%d/%d/%d %d:%d",&junk1,&junk2,&junk3,&searchdate.hour,&searchdate.minute)!=5){
    if(result == -1){
      searchdate.hour = 0;
      searchdate.minute = 0;
    }
    else{
      searchdate.hour = 23;
      searchdate.minute = 59;
    }
  }

  /* jhat - fixing year of user input to the most recent occurence of that date */

  if (time(&ltime) != -1) {
    curr_time = localtime(&ltime);

    if (curr_time->tm_year > 99) {
    /* subtract 1 century from the current year so that if we are past 2000
        searchdate will be set to the correct century.*/

      curdate.year = curr_time->tm_year - 100;
      curdate.month = curr_time->tm_mon+1;
      curdate.day = curr_time->tm_mday;
      curdate.hour = curr_time->tm_hour;
      curdate.minute = curr_time->tm_min;
      /* keep looping until we pass today-100 years */
      while (comparedates(&searchdate, &curdate)!=-1) {
        searchdate.year = searchdate.year + 100;
      }
    }
  }

  if (acedata==NULL) return;
  q= listroot;
  oldroot = listroot;
  listroot = NULL;
  
  while(q!=NULL){
    clone = arrp(acedata,q->index,CLONE);
    if(created)
      cmpdate = clone->creation_date;
    else
      cmpdate = clone->modified_date;
    if(comparedates(&searchdate,&cmpdate)==result){
      if(first){
	listroot  = (struct list *)messalloc((sizeof(struct list)));	
	listroot->next = NULL;
	p = listroot;
	p->index = q->index;
	first = FALSE;
      }
      else{
	p->next = (struct list *)messalloc((sizeof(struct list)));	
	p=p->next;
	p->index = q->index;
      }
    }
    q=q->next;
  }
  if(listroot==NULL){
   listroot = oldroot;
    i=0;
    while(oldroot != NULL){
      i++;
      oldroot= oldroot->next;
    }
    if (created)
      sprintf(str1,"Clone search (Created Date) failed for keyset of %d items.", i);
    else
      sprintf(str1,"Clone search (Modified Date) failed for keyset of %d items.", i);
    if (PRTMESS) displaymess(str1);
    displaykeyset(0);
  }
  else{
    page = 0;
    p= oldroot;
    while(p!=NULL){
      temp=p;
      p=p->next;
      if(!messfree(temp))
        printf("error freeing list memory\n");
    }
    displaykeyset(1);
  }
  graphPop();
}
/*****************************************************
             DEF: ctgclonesearch
*******************************************************/
void ctgclonesearch()
{
  char search[CLONE_SZ+1];
  BOOL added,first=TRUE;
  struct list *p=NULL,*oldroot,*temp,*q;
  CLONE *clone;
  int ctg,i;

  strcpy(search,chsearchglob);
  destarandlower(search);
  if(!sscanf(search,"%d",&ctg)){
     printf("%s is not an integer. Try again\n",search);
     return;
  }
   
  if (acedata==NULL) return;
  q= listroot;
  oldroot = listroot;
  listroot = NULL;

  while(q!=NULL){
    added =FALSE;
    clone = arrp(acedata,q->index,CLONE);
    if(clone->ctg == ctg){
      added = TRUE;
      if(first){
	listroot  = (struct list *)messalloc((sizeof(struct list)));	
	listroot->next = NULL;
	p = listroot;
	p->index = q->index;
	first = FALSE;
      }
      else{
	p->next = (struct list *)messalloc((sizeof(struct list)));	
	p=p->next;
	  p->index = q->index;
      }
    }
    q=q->next;
  }
  if(listroot==NULL){
    listroot = oldroot;
    i=0;
    while(oldroot != NULL){
      i++;
      oldroot= oldroot->next;
    }
    printf("Clone search (Contig=%d) failed for keyset of %d items.\n",ctg, i);
    displaykeyset(0);
  }
  else{
    page = 0;
    p= oldroot;
    while(p!=NULL){
      temp=p;
      p=p->next;
      if(!messfree(temp))
        printf("error freeing list memory\n");
    }
    displaykeyset(1);
  }
  graphPop();
}

/*****************************************************
             DEF: gtNbands
*******************************************************/
void gtNbands()
{
  char search[CLONE_SZ+1];
  BOOL added,first=TRUE;
  struct list *p=NULL,*oldroot,*temp,*q;
  CLONE *clone;
  int n,i;

  strcpy(search,chsearchglob);
  destarandlower(search);
  if(!sscanf(search,"%d",&n)){
     printf("%s is not an integer. Try again\n",search);
     return;
  }
   
  if (acedata==NULL) return;
  q= listroot;
  oldroot = listroot;
  listroot = NULL;

  while(q!=NULL){
    added =FALSE;
    clone = arrp(acedata,q->index,CLONE);
    if (clone->fp == NULL) return;

    if(clone->fp->b2 >= n){
      added = TRUE;
      if(first){
	listroot  = (struct list *)messalloc((sizeof(struct list)));	
	listroot->next = NULL;
	p = listroot;
	p->index = q->index;
	first = FALSE;
      }
      else{
	p->next = (struct list *)messalloc((sizeof(struct list)));	
	p=p->next;
	  p->index = q->index;
      }
    }
    q=q->next;
  }
  if(listroot==NULL){
    listroot = oldroot;
    i=0;
    while(oldroot != NULL){
      i++;
      oldroot= oldroot->next;
    }
    printf("Clone search (>= %d bands) failed for keyset of %d items.\n",n, i);
    displaykeyset(0);
  }
  else{
    page = 0;
    p= oldroot;
    while(p!=NULL){
      temp=p;
      p=p->next;
      if(!messfree(temp))
        printf("error freeing list memory\n");
    }
    displaykeyset(1);
  }
  graphPop();
}

